home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
news
/
readers
/
nn-tk.001
/
nn-tk~
/
nn
/
proto.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-25
|
4KB
|
189 lines
/*
* (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
*
* Master/slave communication and locking.
*/
#include "config.h"
#include <signal.h>
#include <errno.h>
#include <pwd.h>
#include "proto.h"
/* proto.c */
static void write_lock __APROTO((char *lock, char *operation));
static int read_lock __APROTO((char *lock));
#ifndef ACCOUNTING
#ifdef AUTHORIZE
#define ACCOUNTING
#endif
#endif
import char *master_directory, *db_directory;
#define HOSTBUF 80
export char proto_host[HOSTBUF]; /* host having the lock */
/*
* When setting a lock, we must check a little later that
* we really got the lock set, i.e. that another process
* didn't set it at the same time!
*/
#define LOCK_SAFETY 5 /* seconds */
/*
* proto_lock(program, mode)
*
* Returns:
* -1 Not running.
* 0 Running, no permission (PL_WAKEUP_SOFT)
* 0 Lock set (PL_SET)
* 1 Lock not set (PL_SET) (another is running)
* 1 Locked and running (PL_WAKEUP)
* pid Locked and running (PL_CHECK)
*/
static void
write_lock(lock, operation)
char *lock, *operation;
{
FILE *m_pid;
char host[HOSTBUF];
m_pid = open_file(lock, OPEN_CREATE);
if (m_pid == NULL)
sys_error("Cannot %s lock file: %s", operation, lock);
nn_gethostname(host, HOSTBUF);
fprintf(m_pid, "%d\n%s\n", process_id, host);
fclose(m_pid);
}
static int read_lock(lock)
char *lock;
{
FILE *m_pid;
char host[HOSTBUF];
char pid[10];
pid[0] = NUL;
proto_host[0] = NUL;
m_pid = open_file(lock, OPEN_READ);
if (m_pid == NULL) return -2; /* no lock */
fgets(pid, 10, m_pid);
fgets(proto_host, HOSTBUF, m_pid);
fclose(m_pid);
if (pid[0] == NUL) return 0; /* corrupted lock */
if (proto_host[0] != NUL) {
substchr(proto_host, NL, NUL);
nn_gethostname(host, HOSTBUF);
if (strncmp(proto_host, host, HOSTBUF) != 0)
return -1; /* locked by another host */
proto_host[0] = NUL;
}
return atoi(pid);
}
int
proto_lock(prog, command)
int prog;
int command;
{
int try, pid;
char *lock = NULL;
switch (prog) {
case I_AM_SPEW:
lock = relative(master_directory, "WPID");
break;
#ifdef ACCOUNTING
case I_AM_ACCT:
lock = relative(db_directory, "LCK..acct");
break;
#endif
case I_AM_NN:
lock = relative(nn_directory, "LOCK");
break;
default:
sys_error("Invalid LOCK prog");
}
if (command == PL_TRANSFER) {
write_lock(lock, "transfer");
return 1;
}
if (command == PL_CLEAR)
goto rm_lock;
try = 1;
again:
switch (pid = read_lock(lock)) {
case -2:
goto no_lock;
case -1: /* wrong host */
return 1;
case 0:
case 1:
case 2: /* corrupted lock file */
if (who_am_i == I_AM_NN) goto rm_lock;
if (--try < 0) goto rm_lock;
sleep(LOCK_SAFETY); /* maybe it is being written */
goto again;
default:
break;
}
if (kill(pid, command == PL_TERMINATE ? SIGHUP : SIGALRM) == 0) {
switch (command) {
case PL_SET_QUICK:
sleep(1);
goto again;
case PL_SET_WAIT:
case PL_CLEAR_WAIT:
sleep(30);
goto again;
case PL_CHECK:
return pid;
default:
return 1;
}
}
if (command == PL_CHECK)
return (errno == EPERM) ? pid : -1;
if (command == PL_WAKEUP_SOFT)
return (errno == EPERM) ? 0 : -1;
/* lock file contains a non-existing process, or a process with */
/* wrong owner, ie. neither master or expire, so remove it */
rm_lock:
unlink(lock);
no_lock:
if (command != PL_SET && command != PL_SET_QUICK && command != PL_SET_WAIT)
return -1;
write_lock(lock, "create");
/* a user will not start nn twice at the exact same time! */
if (who_am_i == I_AM_NN || command == PL_SET_QUICK) return 0;
sleep(LOCK_SAFETY);
if (read_lock(lock) != process_id)
return 1; /* somebody stole the lock file */
return 0; /* lock is set */
}